package com.b2.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.model.PartETag;
import com.b2.constant.MessageConstant;
import com.b2.mapper.VideoMapper;
import com.b2.pojo.dto.MergeDto;
import com.b2.pojo.entity.Video;
import com.b2.result.Result;
import com.b2.service.VideoService;
import com.b2.utils.AliOssUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
* @author 悦神
* @description 针对表【video】的数据库操作Service实现
* @createDate 2024-04-25 16:05:17
*/
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video>
    implements VideoService{

    // 注入VideoMapper接口对象
    @Resource
    private VideoMapper videoMapper;

    // 注入阿里云oss接口对象
    @Resource
    private AliOssUtil aliOssUtil;

    @Override
    public Result<List<Video>> listAll(Long courseId) {
        // 根据课程id查询视频
        LambdaQueryWrapper<Video> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(courseId != null, Video::getCourseId, courseId);
        List<Video> videoList = videoMapper.selectList(lambdaQueryWrapper);
        // if(videoList.size() == 0) throw new RuntimeException(MessageConstant.VIDEO_NOT_EXIST);
        return Result.success(videoList);
    }

    @Override
    @Transactional
    public void delete(Long videoId) {
        // 通过videoId获取视频资源地址
        String videoUrl = videoMapper.selectById(videoId).getVideoUrl();
        // 通过videoId删除视频数据
        videoMapper.deleteById(videoId);
        // 将阿里云oss的视频资源删除
        aliOssUtil.deleteFile(videoUrl);
    }

//    // 查询分块文件是否存在
//    // todo
//    @Override
//    public Result<Boolean> checkChunk(MultipartUploadDto multipartUploadDto) {
//        // 获取分块文件所在目录的路径
//        String chunkFileFolderPath = this.getChunkFileFolderPath(multipartUploadDto.getFileMd5());
//
//        // 获取原始数据名
//        String originalFilename = multipartUploadDto.getFile().getOriginalFilename();
//        // 获取后缀名
//        String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
//        // 生成完整分块文件路径
//        String objectName = chunkFileFolderPath + multipartUploadDto.getChunkIndex()  + suffixName;
//
//        // 如果数据库中视频数据存在，则查询oss中是否存在
//        boolean result = aliOssUtil.checkFile(objectName);
//        if(result) return Result.success();
//        else return Result.error("该分块文件不存在，可以上传该分块文件");
//    }

    // 查询视频文件是否存在
    @Override
    public Result<Boolean> checkFile(String fileMd5, String fileName) {
        // 获取视频文件的路径
        String objectName = this.getObjectName(fileMd5, fileName);

        //查询视频文件
        LambdaQueryWrapper<Video> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Video::getFileMd5, fileMd5);
        Video video = videoMapper.selectOne(lambdaQueryWrapper);

        if (video != null) {
            // 如果数据库中视频数据存在，则查询oss中是否存在
            boolean result = aliOssUtil.checkFile(objectName);
            if(result) {
                throw new RuntimeException(MessageConstant.FILE_EXIST);
            }
        }
        //文件不存在
        return Result.success();
    }

    // 上传分块文件
    @Override
    public Result<String> uploadChunk(MultipartFile file, String fileMd5, String fileName, int chunkIndex, String uploadId) throws IOException, ExecutionException, InterruptedException {
        // 获取视频文件的路径
        String objectName = this.getObjectName(fileMd5, fileName);

        PartETag partETag = aliOssUtil.uploadPart(
                objectName,
                uploadId,
                file.getInputStream(),
                (int) file.getSize(),
                chunkIndex + 1);

        String partETagStr = JSONObject.toJSONString(partETag);

        // 上传成功
        return Result.success(partETagStr);
    }

    // 合并分块文件
    @Override
    @Transactional
    public Result<String> mergeChunks(MergeDto mergeDto) {
        // 获取视频文件的路径
        String objectName = this.getObjectName(mergeDto.getFileMd5(), mergeDto.getFileName());

        List<String> partETags = mergeDto.getPartETags();
        List<PartETag> partETagList = new ArrayList<>();
        for (String partETag : partETags) {
            partETagList.add(JSON.parseObject(partETag, PartETag.class));
        }

        aliOssUtil.completeMultipartUpload(objectName, mergeDto.getUploadId(), partETagList);

        String videoUrl = "https://cdnboard.s3.syssts.com/" + objectName;

        // 保存视频文件到数据库
        Video video = mergeDto.getVideo();
        video.setVideoUrl(videoUrl);
        videoMapper.insert(video);
        return Result.success();
    }

    // 获取uploadId
    @Override
    public Result<String> uploadId(String fileMd5, String fileName) {
        // 获取视频文件的路径
        String objectName = this.getObjectName(fileMd5, fileName);
        // 初始化分块
        String uploadId = aliOssUtil.initMultiPartUpload(objectName);
        return Result.success(uploadId);
    }

    //得到文件的目录
    private String getFileFolderPath(String fileMd5) {
        return "web/video/" + fileMd5.charAt(0) + "/" + fileMd5.charAt(1) + "/";
    }

    // 获取objectName
    private String getObjectName(String fileMd5, String fileName) {
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        return getFileFolderPath(fileMd5) + fileMd5 + suffixName;
    }

}




